#include "HoleListModel.h"

#include "StringFormatter.h"

#include "LeIpc2581/enumtranslator.h"
#include "LeIpc2581/Hole.h"

#include <QDebug>
#include <QHash>
#include <QSet>

struct HoleItem
{
    HoleItem():
        hole(nullptr)
    {}

    explicit HoleItem(const Ipc2581b::Hole *hole):
        hole(hole)
    {}

    const Ipc2581b::Hole *hole;
};

class HoleListModelPrivate
{
    Q_DISABLE_COPY(HoleListModelPrivate)
    Q_DECLARE_PUBLIC(HoleListModel)
    HoleListModel * const q_ptr;

    explicit HoleListModelPrivate(HoleListModel *model):
        q_ptr(model)
    {}

    QList<HoleItem> m_data;

    inline void clear()
    {
        m_data.clear();
    }
};

HoleListModel::HoleListModel(QObject *parent):
    QAbstractTableModel(parent),
    d_ptr(new HoleListModelPrivate(this))
{
}

HoleListModel::~HoleListModel()
{

}

void HoleListModel::addHole(const Ipc2581b::Hole *hole)
{
    Q_D(HoleListModel);
    d->m_data.append(HoleItem(hole));
}

void HoleListModel::clear()
{
    Q_D(HoleListModel);

    beginResetModel();
    d->clear();
    endResetModel();
}

QVariant HoleListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation != Qt::Horizontal)
        return QVariant();

    if (role != Qt::DisplayRole)
        return QVariant();

    switch (section)
    {
        case NameColumn:
            return "Name";
        case DiameterColumn:
            return "Diameter";
        case PlatingColumn:
            return "Plating";
        case LocationColumn:
            return "Location";
        case ToleranceColumn:
            return "Tolerance";
        default:
            return QVariant();
    }
}

int HoleListModel::rowCount(const QModelIndex &parent) const
{
    Q_D(const HoleListModel);

    if (parent.isValid())
        return 0;

    return d->m_data.count();
}

int HoleListModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return ColumnCount;
}

QVariant HoleListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (index.row() < 0 || index.row() >= rowCount())
        return QVariant();

    Q_D(const HoleListModel);
    const HoleItem item = d->m_data.value(index.row());
    const Ipc2581b::Hole *hole = item.hole;

    switch (role)
    {
        case Qt::DisplayRole:
            switch (index.column())
            {
                case NameColumn:
                    return hole->name;
                case DiameterColumn:
                    return hole->diameter;
                case PlatingColumn:
                    return Ipc2581b::EnumTranslator::platingStatusText(hole->platingStatus);
                case LocationColumn:
                    return StringFormatter::pointF(hole->x, hole->y);
                case ToleranceColumn:
                    return StringFormatter::tolerance(hole->plusTol, hole->minusTol);
                default:
                    return QVariant();
            }
        case Qt::EditRole:
            switch (index.column())
            {
                case NameColumn:
                    return hole->name;
                case DiameterColumn:
                    return hole->diameter;
                case PlatingColumn:
                    return QVariant::fromValue<Ipc2581b::PlatingStatus>(hole->platingStatus);
                case LocationColumn:
                    return QPointF(hole->x, hole->y);
                case ToleranceColumn:
                    return QPointF(hole->plusTol, hole->minusTol); // FIXME
                default:
                    return QVariant();
            }
        default:
            return QVariant();
    }
}
